

#ifndef UC_GEPNT3D_H
#define UC_GEPNT3D_H

#include "zgevec3d.h"
#pragma pack (push, 8)

class UcGeMatrix3d;
class UcGeLinearEnt3d;
class UcGePlane;
class UcGePlanarEnt;
class UcGeVector3d;
class UcGePoint2d;

class
GE_DLLEXPIMPORT
UcGePoint3d
{
public:
    UcGePoint3d();
    UcGePoint3d(const UcGePoint3d& pnt);
    UcGePoint3d(double x, double y, double z);
    UcGePoint3d(const UcGePlanarEnt& pln, const UcGePoint2d& pnt2d);

    static const   UcGePoint3d    kOrigin;

    friend
GE_DLLEXPIMPORT
    UcGePoint3d    operator *  (const UcGeMatrix3d& mat, const UcGePoint3d& pnt);
    UcGePoint3d&   setToProduct(const UcGeMatrix3d& mat, const UcGePoint3d& pnt);

    UcGePoint3d&   transformBy (const UcGeMatrix3d& leftSide);
    UcGePoint3d&   rotateBy    (double angle, const UcGeVector3d& vec,
                                const UcGePoint3d& wrtPoint = UcGePoint3d::kOrigin);
    UcGePoint3d&   mirror      (const UcGePlane& pln);
    UcGePoint3d&   scaleBy     (double scaleFactor, const UcGePoint3d&
                                wrtPoint = UcGePoint3d::kOrigin);
    UcGePoint2d    convert2d   (const UcGePlanarEnt& pln) const;

    UcGePoint3d    operator *  (double scl) const;
    friend
    UcGePoint3d    operator *  (double scl, const UcGePoint3d& pnt);
    UcGePoint3d&   operator *= (double scl);
    UcGePoint3d    operator /  (double scl) const;
    UcGePoint3d&   operator /= (double scl);

    UcGePoint3d    operator +  (const UcGeVector3d& vec) const;
    UcGePoint3d&   operator += (const UcGeVector3d& vec);
    UcGePoint3d    operator -  (const UcGeVector3d& vec) const;
    UcGePoint3d&   operator -= (const UcGeVector3d& vec);
    UcGePoint3d&   setToSum    (const UcGePoint3d& pnt, const UcGeVector3d& vec);

    UcGeVector3d   operator -  (const UcGePoint3d& pnt) const;
    UcGeVector3d   asVector    () const;

    double         distanceTo       (const UcGePoint3d& pnt) const;

    UcGePoint3d    project       (const UcGePlane& pln, const UcGeVector3d& vec) const;
    UcGePoint3d    orthoProject  (const UcGePlane& pln) const;

    bool operator == (const UcGePoint3d& pnt) const;
    bool operator != (const UcGePoint3d& pnt) const;
    bool isEqualTo   (const UcGePoint3d& pnt,
                                const UcGeTol& tol = UcGeContext::gTol) const;

    double         operator [] (unsigned int i) const;
    double&        operator [] (unsigned int idx);
    UcGePoint3d&   set         (double x, double y, double z);
    UcGePoint3d&   set         (const UcGePlanarEnt& pln, const UcGePoint2d& pnt);

    double         x, y, z;
};

ZSOFT_FORCE_INLINE
UcGePoint3d::UcGePoint3d() : x(0.0), y(0.0), z(0.0)
{
}

ZSOFT_FORCE_INLINE
UcGePoint3d::UcGePoint3d(const UcGePoint3d& src) : x(src.x), y(src.y), z(src.z)
{
}

ZSOFT_FORCE_INLINE
UcGePoint3d::UcGePoint3d(double xx, double yy, double zz) : x(xx), y(yy), z(zz)
{
}

ZSOFT_FORCE_INLINE bool
UcGePoint3d::operator == (const UcGePoint3d& p) const
{
    return this->isEqualTo(p);
}

ZSOFT_FORCE_INLINE bool
UcGePoint3d::operator != (const UcGePoint3d& p) const
{
    return !this->isEqualTo(p);
}

ZSOFT_FORCE_INLINE UcGePoint3d
UcGePoint3d::operator * (double val) const
{
    return UcGePoint3d(x*val, y*val, z*val);
}

ZSOFT_FORCE_INLINE UcGePoint3d
operator * (double val, const UcGePoint3d& p)
{
    return UcGePoint3d(p.x*val, p.y*val, p.z*val);
}

ZSOFT_FORCE_INLINE UcGePoint3d&
UcGePoint3d::operator *= (double val)
{
    x *= val;
    y *= val;
    z *= val;
    return *this;
}

ZSOFT_FORCE_INLINE UcGePoint3d
UcGePoint3d::operator / (double val) const
{
    return UcGePoint3d (x/val, y/val, z/val);
}

ZSOFT_FORCE_INLINE UcGePoint3d&
UcGePoint3d::operator /= (double val)
{
    x /= val;
    y /= val;
    z /= val;
    return *this;
}

ZSOFT_FORCE_INLINE UcGePoint3d
UcGePoint3d::operator + (const UcGeVector3d& v) const
{
    return UcGePoint3d (x + v.x, y + v.y, z + v.z);
}

ZSOFT_FORCE_INLINE UcGePoint3d&
UcGePoint3d::operator += (const UcGeVector3d& v)
{
    x += v.x;
    y += v.y;
    z += v.z;
    return *this;
}

ZSOFT_FORCE_INLINE UcGePoint3d
UcGePoint3d::operator - (const UcGeVector3d& v) const
{
    return UcGePoint3d (x - v.x, y - v.y, z - v.z);
}

ZSOFT_FORCE_INLINE UcGePoint3d&
UcGePoint3d::operator -= (const UcGeVector3d& v)
{
    x -= v.x;
    y -= v.y;
    z -= v.z;
    return *this;
}

ZSOFT_FORCE_INLINE UcGeVector3d
UcGePoint3d::operator - (const UcGePoint3d& p) const
{
    return UcGeVector3d (x - p.x, y - p.y, z - p.z);
}

ZSOFT_FORCE_INLINE UcGeVector3d
UcGePoint3d::asVector() const
{
    return UcGeVector3d(x, y, z);
}

ZSOFT_FORCE_INLINE UcGePoint3d&
UcGePoint3d::set(double xx, double yy, double zz)
{
    x = xx;
    y = yy;
    z = zz;
    return *this;
}

ZSOFT_FORCE_INLINE double
UcGePoint3d::operator [] (unsigned int i) const
{
    return *(&x+i);
}

ZSOFT_FORCE_INLINE double&
UcGePoint3d::operator [] (unsigned int i)
{
    return *(&x+i);
}

#define ZSOFT_UCGEPOINT3D_DEFINED
#include "zacarrayhelper.h"

#pragma pack (pop)
#endif
